<?php
use frontend\modules\yii2\widgets\layouts\markdown\Markdown;
/* @var $this \yii\web\View */
$this->title = 'Web路由设置-urlManager组件-Components组件';
$this->registerMetaTag([
    'name' => 'keywords',
    'content' => 'yii,yii2,框架,应用组件,Components,使用,教程,urlManager,路由机制,web'
]);
$this->registerMetaTag([
    'name' => 'description',
    'content' => 'Yii的路由机制非常灵活，而urlManager的功能就是管理路由，这是Yii中必学的内容，掌握这个利器可以让您的应用变得更加优雅。'
]);

$html = [
    "概述" => <<<HTML
# Web路由设置
在本节中，我们重点讲一下在`urlManager->rules[]`中的默认路由解析器（`yii\web\UrlRule`）的功能。当Yii收到我们在浏览器中输入的url时，会根据`rules`中的规则进行映射，找到最终的控制器方法，实现请求的响应。

> **注意：** 只有在`'enablePrettyUrl' = true`的情况下，Yii才会对rules进行解析，否则rules无效。

HTML,
    "config" => <<<HTML
## 配置举例 id=config
`rules`的配置举例如下：
```php
[
    'components' => [
        'urlManager' => [
            'enablePrettyUrl' => true, // 必须为true，否则rules的设置无效
            'showScriptName' => false,
            'ruleConfig' => ['class' => 'yii\web\UrlRule'], // 这是默认的路由解析器
            'rules' => [
                'dashboard' => 'site/index',
                'POST <controller:[\w-]+>' => '<controller>/create',
                '<controller:[\w-]+>s' => '<controller>/index',
                'PUT,POST <controller:[\w-]+>/<id:\d+>'    => '<controller>/update',
                'DELETE <controller:[\w-]+>/<id:\d+>' => '<controller>/delete',
                '<controller:[\w-]+>/<id:\d+>'        => '<controller>/view',
            ]
        ]
    ],
]
```
上面的是简写方式，完整的配置方法：
```php
'urlManager' => [
    'enablePrettyUrl' => true,
    'showScriptName' => false,
    'rules' => [
        // 简写
        // '/about' => '/site/contact',
        // 完整写法
        [
            'class' => 'yii\web\UrlRule',
            'pattern' => 'posts/<page:\d+>/<tag>',      // 输入的url，可以包含正则表达式
            'route' => 'post/index',    // 解析后的url
            'verb' => ['GET'],          // 允许的http访问方法
            'suffix' => '.html',        // 浏览器中url的后缀，别忘记有.号
            'mode' => \yii\web\UrlRule::PARSING_ONLY,   // 只在解析请求中使用
            'defaults' => ['page' => 1, 'tag' => ''],   // 设置默认参数
        ]
    ]
]
```
HTML,
    "方法设定" => <<<HTML
## 限制访问方法（verb） id=verb
常见的访问方法有：GET、POST、DELETE、PUT、OPTIONS、HEAD。我们在[权限管理](/docs/structure/controller/web#verbs)一节中讲解了在控制器中限制访问方法的功能，但您也可以选择在路由阶段就实施方法过滤，举例如下：
```php
'rules' => [
    'POST users' => 'user/create',
    'PUT,POST users/<id:\d+>'    => 'user/update',
    'DELETE users/<id:\d+>' => 'user/delete',
]
```
上述路由都是对`user`进行操作，但是通过不同的访问方法映射到了不同的控制器动作，统一了对`user`接口各种操作（增删改查），这么做的好处是：客户端需要管理的接口减少了。
HTML,
    "pattern" => <<<HTML
## Url匹配规则（pattern） id=pattern
Url匹配规则的最大特色就是允许使用正则表达式，使用正则表达式有如下优点：
- 极大缩减了路由规则数量；
- 允许对url中参数位置和数据类型进行设置，提前过滤无效url的访问；
- 可以指定参数名称，并在控制器中直接使用，跳过了从`\$_GET`这些全局变量中取数的工作；


HTML,
    "完整匹配" => <<<HTML
### 完整匹配　id=complete
如果你只是想要把浏览器输入的内容当作一个完整的字符串映射到指定控制器动作，可以使用如下方法：
```php
'rules' => [
    [
        'pattern' => 'users',
        'route' => 'user/index',
    ]
]
```
此时浏览器输入：`http://hostname/users`就会访问到`user/index`，这是常用的一种匹配方法。

HTML,
    "数字匹配" => <<<HTML
### 数字匹配 id=digital
在url中加入id也是常用的访问方式，此时可以通过正则指定：
```php
'rules' => [
    [
        'pattern' => 'users/<id:\d+>',
        'route' => 'user/view',
    ]
]
```
上述代码表示您必须在`/users/`后增加一个数字，否则无法解析到`user/view`，比如：
```shell
// 获取id = 1的用户信息
http://hostname/users/1
```
强制设定数学类型的好处是可以提高系统安全性，当然您还需要在model中进行id校验，避免当前用户获取其他用户的信息。
HTML,
    "参数长度匹配" => <<<HTML
### 长度匹配 id=length
除了匹配数据类型外，还可以匹配数据长度，比如说年份：
```php
'rules' => [
    [
        'class' => 'yii\web\UrlRule',
        'pattern' => 'posts/<year:\d{4}>',
        'route' => 'post/index',
    ]
]
```
上述代码表示url必须带有4位数字，如：
```shell
http://hostname/posts/2012
```
HTML,
    "枚举匹配" => <<<HTML
### 枚举匹配 id=enum
如果当前路由只能提供给有限的控制器使用，那可以选择枚举匹配：
```php
'rules' => [
    [
        'pattern' => '<controller:(post|comment)>/<id:\d+>/<action:(update|delete)>',
        'route' => '<controller>/<action>',
    ]
]
```
上述规则表明只能接受`post`或者`comment`控制器的`update`或者`delete`方法组成的url，如：
```shell
// 更新post数据表id=1的内容
http://hostname/post/1/update

// 删除comment数据表id=1的内容
http://hostname/comment/1/delete
```
HTML,
    "参数默认值" => <<<HTML
## 参数默认值（defaults） id=defaults
在上述[Pattern](#pattern)一节中我们介绍了如何在url中携带参数，当请求的url没有携带参数的时候，无法匹配对应的路由。但是我们可以通过设置`defaults`属性，将必填参数转化为可选参数，当url中没有携带参数时，会使用`defaults`中指定的默认值：
```php
[
    // ...其它规则...
    [
        'pattern' => 'posts/<page:\d+>/<tag>',
        'route' => 'post/index',
        'defaults' => ['page' => 1, 'tag' => ''],
    ],
]
```
上面的规则可以用来解析或创建下面的 URL：
- `/index.php/posts`：page 为 1，tag 为 ''。
- `/index.php/posts/2`：page 为 2，tag 为 ''。
- `/index.php/posts/2/news`：page 为 2，tag为 'news'。
- `/index.php/posts/news`：page 为 1，tag 为 'news'。

HTML,
    "匹配目标" => <<<HTML
## 路由结果（route） id=route
这个属性表示真实的访问终点，也支持正则匹配：
```php
'rules' => [
    [
        'pattern' => '<controller:(post|comment)>/<id:\d+>/<action:(update|delete)>',
        'route' => '<controller>/<action>',
    ]
]
```
上述路由中，`pattern`中的`controller`和`action`字符串会同步到`route`的相应位置。

HTML,
    "格式后缀" => <<<HTML
## 格式后缀（suffix） id=suffix
添加合适的url后缀可以让客户端开发人员知道返回怎样的数据，比如说调用接口，返回的数据是json格式的，此时您可以这么配置：
```php
[
    'components' => [
        'urlManager' => [
            'enablePrettyUrl' => true,
            'suffix' => '.html',
            'rules' => [
                [
                    'pattern' => 'users/<id:\d+>',
                    'route' => 'user/view',
                    'suffix' => '.json',
                ],
            ],
        ],
    ],
]
```
上述路由表示您的url中必须要带有`.json`后缀，这么做可以明确告诉前端开发人员访问此url会返回json格式的数据：
```shell
http://hostname/users/1.json
```
HTML,
    "" => <<<HTML

HTML,
];

echo Markdown::widget(["content" => implode("\n", $html)]);

